﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.IO;

namespace System.Runtime.Serialization.Advanced
{
  public class ClassGraph
  {
    private Type _type;
    
  }

  [Serializable]
  public class DataContract
  {
    public string DataSetName { get; set; }
    public int Revision { get; set; }
    public string[] FieldNames { get; set; }
    public string[] ChildrenNames { get; set; }
    public List<DataContract> ChildDescriptions { get; set; }

    public DataContract(Type type)
    {
      ChildDescriptions = new List<DataContract>();
      DataContractAttribute att = type.GetCustomAttribute<DataContractAttribute>();
      DataSetName = att.DataSetName ?? type.FullName;
      Revision = att.Revision;
      List<String> names = new List<string>();

      foreach(FieldInfo field in type.GetFields().Where(x=>x.HasCustomAttribute<DataFieldAttribute>()))
      {
        DataFieldAttribute df = field.GetCustomAttribute<DataFieldAttribute>();
        Revision = Math.Max(Revision, df.Revision);
        names.Add(df.Name ?? field.Name);

        if(typeof(IGraphable).IsAssignableFrom(field.FieldType))
          ChildDescriptions.Add(new Advanced.DataContract(field.FieldType));
      }

    }
  }

  public class DataGraph
  {

    //public class DataDescriptionSet
    //{
    //  DataDescription Description { get; private set; }
    //  List<object> Data { get; private set; }

    //  public DataDescriptionSet(DataDescription desc) { Data = new List<object>(); Description = desc; }
    //}

    //private Dictionary<Type, DataDescriptionSet> _dataTypes = new Dictionary<Type, DataDescriptionSet>();
    private Dictionary<Type, List<IGraphable>> _data1 = new Dictionary<Type, List<IGraphable>>();
    private Dictionary<Type, DataContract> _dataDescriptions = new Dictionary<Type, DataContract>();

    public Dictionary<Type, DataContract> DataDescriptions
    {
      get { return _dataDescriptions; }
      set { _dataDescriptions = value; }
    }


    public Dictionary<Type, List<IGraphable>> Data1
    {
      get { return _data1; }
      set { _data1 = value; }
    }

    //[Data Type][Object][Object Data]
    private Dictionary<Type, Dictionary<object, object[]>> _data = new Dictionary<Type, Dictionary<object, object[]>>();
    private Dictionary<Type, string[]> _fieldNames = new Dictionary<Type, string[]>();
    private readonly List<IGraphable> _rootObjects = new List<IGraphable>();

    private List<IGraphable> _objects = new List<IGraphable>();
    private int[] _children;
    
    public DataGraph(params IGraphable[] source)
    {
      System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf;
      _rootObjects = new List<IGraphable>(source);
      Add(_rootObjects);
    }

    ////Revision, Fields,Children. Return object
    //public IEnumerable<object> Get(Func<DataDescription,Stream,object[],object> factory)
    //{
    //  foreach (Object obj in _rootObjects)
    //    yield return factory(obj);
    //}

    public int Add(IGraphable obj)
    {
      Type t = obj.GetType();
      List<IGraphable> list = _data1[t];// ?? (_data1[t] = new List<IGraphable>());
      if (list == null)
      {
        _dataDescriptions[t] = new DataContract(obj);
        list = _data1[t] = new List<IGraphable>();
      }
      if (list.Contains(obj))
        return list.IndexOf(obj);

      list.Add(obj);
      return list.Count - 1;
    }

    public void Add(IEnumerable<IGraphable> objs)
    {
      if (objs.Count() == 0)
        return;
      IGraphable o = objs.FirstOrDefault();
      Type t = o.GetType();
      List<IGraphable> list = _data1[t];// ?? (_data1[t] = new List<IGraphable>());
      if (list == null)
      {
        _dataDescriptions[t] = new DataContract(obj);
        list = _data1[t] = new List<IGraphable>();
      }

      foreach (var obj in objs)
        if (!list.Contains(obj))
          list.Add(obj);
    }
  }
}
